package agent;

import java.util.ArrayList;
import java.util.Date;
import java.util.Random;

import settings.Settings;

import driver.Move;
import environment.environment;
import driver.sysDriver;

public class agent implements Runnable {
	
	int side, ID, status, currentX, currentY, nextX, nextY, direction, baseFound;

	public int moveSuccess;
	
	reconData myData;
	environment map;
	sysDriver coordinate;
	
	int [][] memEnviron;
	int [][] memHits;
	Date [][] memDate;
	
	public agent( int ID, environment map, sysDriver coordinate, int nowX, int nowY ) {
		
		this.ID = ID;
		this.side = Settings.side;
		this.map = map;
		this.coordinate = coordinate;
		this.currentX = nowX;
		this.currentY = nowY;
		
		moveSuccess = 0;
		baseFound = 0;
		
		memEnviron = new int[ side ][ side ];
		memDate = new Date[ side ][ side ];
		memHits = new int[ side ][ side ];
		for( int i = 0; i < side; i++ ) {
			for( int j = 0; j < side; j++ ) {
				
				memEnviron[ i ][ j ] = -1;
				memDate[ i ][ j ] = null;
				memHits[ i ][ j ] = 0;
			}
		}
		
		map.setAgent(currentX, currentY, ID);
	}
	
	public void buildRoad( int cellValue, int xVal, int yVal ) {
		/*
		try {
			Thread.sleep(20000);
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		*/
		map.changeEnvironment( xVal, yVal, cellValue );
	}
	
	public void observe() {
		
		myData = map.reconArea( ID, currentX, currentY );
		
		int counter = 0;
		
		for( int i = currentY - 1; i < currentY + 2; i++ ) {
			for( int j = currentX - 1; j < currentX + 2; j++ ) {
				
				if( myData.areaRecon[ counter ] != -1 ) {
						
					memDate[ i ][ j ] = myData.reconTime[ counter ];
					memEnviron[ i ][ j ] = myData.areaRecon[ counter ];
				}
				
				if( myData.areaRecon[ counter ] == 6 ) {
					
					baseFound = 1;
				}
				
				if( myData.areaRecon[ counter ] == 2 || myData.areaRecon[ counter ] == 4 || myData.areaRecon[ counter ] == 5 ) {
					
					memHits[ i ][ j ] = 1000;
				}
				
				counter++;
			}
		}
	}
	
	public void moveForward(Move m) {
		
		coordinate.queueMove(m);
		
		while( moveSuccess == 0 ) {
			
			communicate();
		}
		
		if( moveSuccess == 1 ) {
			
			memHits[ currentY ][ currentX ]++;
			currentX = nextX;
			currentY = nextY;
		}
		
		moveSuccess = 0;
			
	}
	
	public void communicate() {
		
		ArrayList < Integer > nearby;
		
		Date [][] tempDate = new Date[ side ][ side ];
		int [][] tempEnviron = new int[ side ][ side ];
		int [][] tempHits = new int[ side ][ side ];
		
		nearby = map.findFriends( currentX, currentY );
		
		while( nearby.isEmpty() == false ) {
			
			tempDate = Settings.table.allAgents.get( nearby.get( 0 ) ).returnTimes();
			tempEnviron = Settings.table.allAgents.get( nearby.get( 0 ) ).returnEnviron();
			tempHits = Settings.table.allAgents.get( nearby.get( 0 ) ).returnHits();
			
			for( int i = 0; i < side; i++ ) {
				for( int j = 0; j < side; j++ ) {
					
					if( tempDate[ i ][ j ] != null ) {
						if( memDate[ i ][ j ] == null ) { 
						
							memDate[ i ][ j ] = tempDate[ i ][ j ];
							memEnviron[ i ][ j ] = tempEnviron[ i ][ j ];
						}
						else if( tempDate[ i ][ j ].after( memDate[ i ][ j ] ) ) {
							
							memDate[ i ][ j ] = tempDate[ i ][ j ];
							memEnviron[ i ][ j ] = tempEnviron[ i ][ j ];
						}
					}
					
					if( memHits[ i ][ j ] < tempHits[ i ][ j ] ) {
						
						memHits[ i ][ j ] = tempHits[ i ][ j ];
					}
				}
			}
			
			nearby.remove( 0 );
		}
	}
	
	public Date [][] returnTimes() {
		
		return memDate;
	}
	
	public int [][] returnEnviron() {
		
		return memEnviron;
	}
	
	public int [][] returnHits() {
		
		return memHits;
	}
	
	public void testAlgorithm() {
		
		Move moving;
		
		try {
			if( memEnviron[currentY-1][currentX] == 1 /*&& memEnviron[currentY-1][currentX] == 3*/) {
				
				nextX = currentX;
				nextY = currentY -1;
				moving = new Move(ID, nextX, nextY);
				moveForward(moving);
				return;
			}
		}
		catch( ArrayIndexOutOfBoundsException e ) {
		}
		
	
		try {
			if( memEnviron[currentY][currentX-1] == 1 /*&& memEnviron[currentY][currentX-1] == 3*/) {
				
				nextX = currentX-1;
				nextY = currentY;
				moving = new Move(ID, nextX, nextY);
				moveForward(moving);
				return;
			}
		}
		catch( ArrayIndexOutOfBoundsException e ) {
		}			
	}
	
	public void moveAlgorithm1( Random generator ) {
		
		Move moving;
		
		try {
		if( memHits[ currentY - 1][ currentX ] == memHits[ currentY + 1 ][ currentX ] && memHits[ currentY + 1][ currentX ] == memHits[ currentY ][ currentX -1 ] && memHits[ currentY ][ currentX -1 ] == memHits[ currentY][ currentX + 1 ]) {
			int nextMove = generator.nextInt(4);
			switch(nextMove) {
			case 0:
				nextX = currentX;
				nextY = currentY - 1;
				break;
			case 1:
				nextX = currentX - 1;
				nextY = currentY;
				break;
			case 2:
				nextX = currentX;
				nextY = currentY + 1;
				break;
			case 3:
				nextX = currentX + 1;
				nextY = currentY;
				break;
			default:
				break;
					
			}
			
		}
		else {
			
			if( memHits[ currentY - 1][ currentX ] > memHits[ currentY + 1 ][ currentX ] && memHits[ currentY - 1][ currentX ] > memHits[ currentY ][ currentX -1 ] && memHits[ currentY - 1 ][ currentX ] > memHits[ currentY][ currentX + 1 ]) {
				nextX = currentX;
				nextY = currentY - 1;
			}
			else if( memHits[ currentY + 1][ currentX ] > memHits[ currentY - 1 ][ currentX ] && memHits[ currentY + 1][ currentX ] > memHits[ currentY ][ currentX -1 ] && memHits[ currentY + 1 ][ currentX ] > memHits[ currentY][ currentX + 1 ]) {
				nextX = currentX - 1;
				nextY = currentY;
			}
			else if( memHits[ currentY][ currentX - 1 ] > memHits[ currentY - 1 ][ currentX ] && memHits[ currentY][ currentX -1  ] > memHits[ currentY+1 ][ currentX ] && memHits[ currentY ][ currentX-1 ] > memHits[ currentY][ currentX + 1 ] ) {
				nextX = currentX;
				nextY = currentY + 1;
			}
			else if(  memHits[ currentY][ currentX + 1 ] > memHits[ currentY - 1 ][ currentX ] && memHits[ currentY][ currentX +1  ] > memHits[ currentY+1 ][ currentX ] && memHits[ currentY ][ currentX+1 ] > memHits[ currentY][ currentX - 1 ]) {
				nextX = currentX + 1;
				nextY = currentY;
			}
		}
		}
		catch(ArrayIndexOutOfBoundsException e) {
			
		}
		
		
		
		
	}
	
	public void run() {
		
		Random generator = new Random();
		
		observe();
		while( baseFound != 1 ) {
			buildRoad( 3, currentX, currentY);
			testAlgorithm();
			observe();
			try {
				Thread.sleep(700);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			communicate();
		}
		
	}
}
